<template>
  <div id="app" class="app-container">
    <!-- 顶部导航栏 -->
    <header class="app-header">
      <div class="logo">
        <i class="icon-home"></i>
        <h1>电商用户行为分析系统</h1>
      </div>
      <div class="header-actions">
        <button class="theme-toggle" @click="toggleTheme">
          <i :class="darkMode ? 'icon-sun' : 'icon-moon'"></i>
        </button>
        <div class="user-profile">
          <img src="https://picsum.photos/id/1005/40/40" alt="用户头像" class="avatar" />
          <span class="username">数据分析员</span>
        </div>
      </div>
    </header>

    <!-- 主体内容：左侧菜单 + 右侧内容区 -->
    <main class="app-main">
      <!-- 左侧导航菜单 -->
      <aside class="sidebar">
        <nav class="menu">
          <div 
            class="menu-item" 
            :class="{ active: currentChart === null }"
            @click="showWelcome"
          >
            <i class="icon-home"></i>
            <span class="menu-label">首页</span>
          </div>
          <div 
            class="menu-item" 
            v-for="(item, index) in chartOptions" 
            :key="index"
            :class="{ active: currentChart === item.value }"
            @click="selectChart(item.value)"
          >
            <i :class="item.icon"></i>
            <span class="menu-label">{{ item.label }}</span>
          </div>
        </nav>
        <div class="sidebar-footer">
          <div class="copyright">
            <p>© 2025 数据分析平台</p>
            <p class="version">v1.0.0</p>
          </div>
        </div>
      </aside>

      <!-- 右侧内容区 -->
      <section class="content-area">
        <!-- 首页 -->
        <div v-if="currentChart === null" class="welcome-page">
          <h2>欢迎来到电商用户行为分析系统</h2>
          <p class="welcome-time">{{ nowTime }}</p>
          <p class="welcome-tip">请选择左侧菜单，开始数据探索之旅！</p>
        </div>
        <!-- 图表页面 -->
        <template v-else>
          <div class="page-header">
            <h2 class="page-title">{{ currentChartLabel }}</h2>
            <p class="page-desc">{{ chartDescription }}</p>
          </div>
          <div class="chart-container">
            <div class="loading" v-if="loading">
              <div class="loader"></div>
              <p>正在加载数据...</p>
            </div>
            <div class="error" v-else-if="error">
              <i class="icon-error"></i>
              <p>{{ error }}</p>
              <button class="btn-retry" @click="fetchChartData">重试</button>
            </div>
            <div class="chart-wrapper" v-else>
              <component 
                :is="currentChartComponent" 
                :chartData="processedData"
              />
            </div>
          </div>
        </template>
      </section>
    </main>
  </div>
</template>

<script>
import { ref, onMounted, watch, computed, onUnmounted } from 'vue';
// 导入所有图表组件
import CategoryRanking from './components/CategoryRanking.vue';
import GoodsRanking from './components/ProductRanking.vue';
import DailyTrend from './components/DailyTrend.vue';
import HourlyTrend from './components/HourlyTrend.vue';
import ConversionFunnel from './components/ConversionFunnel.vue';
import RFMAnalysis from './components/RFMAnalysis.vue';
import UserRetention from './components/UserRetention.vue';
import axios from 'axios'; 

export default {
  name: 'App',
  components: {
    CategoryRanking,
    GoodsRanking,
    DailyTrend,
    HourlyTrend,
    ConversionFunnel,
    RFMAnalysis,
    UserRetention
  },
  setup() {
    const currentChart = ref(null); // 默认欢迎页
    const processedData = ref([]);
    const loading = ref(false);
    const error = ref(null);
    const darkMode = ref(false);

    // 实时时间
    const nowTime = ref('');
    let timer = null; // 确保 timer 在 setup 作用域内声明
    const updateTime = () => {
      const now = new Date();
      const pad = n => n.toString().padStart(2, '0');
      nowTime.value = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
    };

    // 菜单
    const chartOptions = [
      { label: '每日趋势分析', value: 'dailyTrend', icon: 'icon-trend-day' },
      { label: '每时趋势分析', value: 'hourlyTrend', icon: 'icon-trend-hour' },
      { label: '购买类目排名', value: 'categoryRanking', icon: 'icon-category' },
      { label: '购买商品排名', value: 'goodsRanking', icon: 'icon-goods' },
      { label: '转化漏斗分析', value: 'conversionFunnel', icon: 'icon-funnel' },
      { label: 'RF用户价值分析', value: 'RFMAnalysis', icon: 'icon-rfm' },
      { label: '用户留存分析', value: 'userRetention', icon: 'icon-retention' }
    ];

    const chartDescriptions = {
      dailyTrend: '展示网站流量和用户行为的每日变化趋势',
      hourlyTrend: '分析一天中不同时段的用户活跃度和流量分布',
      categoryRanking: '按购买量排名前10的商品类目',
      goodsRanking: '按销量排名前10的具体商品',
      conversionFunnel: '用户从浏览到购买的转化路径分析',
      RFMAnalysis: '基于最近购买、购买频率的用户价值分类',
      userRetention: '新用户在不同天数后的留存情况'
    };

    const currentChartComponent = computed(() => {
      if (!currentChart.value) return null;
      return currentChart.value.replace(/^[a-z]/, (char) => char.toUpperCase());
    });

    const currentChartLabel = computed(() => {
      const option = chartOptions.find(o => o.value === currentChart.value);
      return option ? option.label : '数据分析';
    });

    const chartDescription = computed(() => {
      return chartDescriptions[currentChart.value] || '详细分析当前所选指标的数据表现';
    });

    // 选择图表
    const selectChart = (val) => {
      currentChart.value = val;
    };
    // 欢迎页
    const showWelcome = () => {
      currentChart.value = null;
    };

    // 数据请求
    const fetchChartData = async () => {
      if (!currentChart.value) return;
      loading.value = true;
      error.value = null;
      try {
        let res;
        switch (currentChart.value) {
          case 'dailyTrend':
            res = await axios.get('http://localhost:8080/trafficTrendData/day');
            processedData.value = res.data.data;
            break;
          case 'hourlyTrend':
            res = await axios.get('http://localhost:8080/trafficTrendData/hour');
            processedData.value = res.data.data;
            break;
          case 'categoryRanking':
            res = await axios.get('http://localhost:8080/top/categories?limit=10');
            processedData.value = res.data.data;
            break;
          case 'goodsRanking':
            res = await axios.get('http://localhost:8080/top/items?limit=10');
            processedData.value = res.data.data;
            break;
          case 'conversionFunnel':
            res = await axios.get('http://localhost:8080/analyze/trafficFunnelConversionAnalysisData');
            processedData.value = res.data.data;
            break;
          case 'RFMAnalysis':
            res = await axios.get('http://localhost:8080/analyze/rfmCustomerAnalysisData');
            processedData.value = res.data.data;
            break;
          case 'userRetention':
            res = await axios.get('http://localhost:8080/analyze/userRetentionAnalysisData');
            processedData.value = res.data.data;
            break;
          default:
            processedData.value = [];
        }
      } catch (e) {
        error.value = '数据加载失败';
        processedData.value = [];
      }
      loading.value = false;
    };

    // 主题切换
    const toggleTheme = () => {
      darkMode.value = !darkMode.value;
      document.documentElement.classList.toggle('dark-mode', darkMode.value);
      localStorage.setItem('darkMode', darkMode.value ? '1' : '0');
    };

    // 初始化
    onMounted(() => {
      // 主题
      darkMode.value = localStorage.getItem('darkMode') === '1';
      document.documentElement.classList.toggle('dark-mode', darkMode.value);
      // 时间
      updateTime();
      timer = setInterval(updateTime, 1000);
    });

    // 切换菜单时拉取数据
    watch(currentChart, (val) => {
      if (val) fetchChartData();
    });

    // 离开页面清理定时器
    onUnmounted(() => {
      timer && clearInterval(timer);
    });

    return {
      currentChart,
      processedData,
      chartOptions,
      currentChartComponent,
      currentChartLabel,
      chartDescription,
      loading,
      error,
      fetchChartData,
      toggleTheme,
      darkMode,
      nowTime,
      selectChart,
      showWelcome
    };
  }
};
</script>

<style>
/* 基础变量和重置 */
:root {
  --primary: #409EFF;
  --primary-light: #66b1ff;
  --primary-dark: #337ecc;
  --secondary: #1f2937;
  --bg: #ffffff;
  --bg-alt: #f9fafb;
  --text: #111827;
  --text-light: #6b7280;
  --border: #e5e7eb;
  --card: #ffffff;
  --card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.05);
  --sidebar-bg: #ffffff;
  --sidebar-item-hover: #f3f4f6;
  --sidebar-item-active: #e6f7ff;
  --sidebar-text: #374151;
  --sidebar-text-active: #1890ff;
  --accent: #ff7a45;
  --success: #52c41a;
  --warning: #faad14;
  --danger: #f5222d;
  --transition: all 0.25s ease;
}

.dark-mode {
  --primary: #5aaaff;
  --primary-light: #86c6ff;
  --primary-dark: #4096ff;
  --secondary: #111827;
  --bg: #0f172a;
  --bg-alt: #111827;
  --text: #e2e8f0;
  --text-light: #94a3b8;
  --border: #1e293b;
  --card: #111827;
  --card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
  --sidebar-bg: #111827;
  --sidebar-item-hover: #1e293b;
  --sidebar-item-active: #1e3a8a;
  --sidebar-text: #e2e8f0;
  --sidebar-text-active: #7dd3fc;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Inter', 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: var(--bg);
  color: var(--text);
  height: 100vh;
  overflow: hidden;
  transition: var(--transition);
}

/* 主容器布局 */
.app-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

/* 顶部导航栏 */
.app-header {
  background: linear-gradient(90deg, var(--primary), var(--primary-dark));
  color: white;
  padding: 0 24px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  z-index: 100;
}

.logo {
  display: flex;
  align-items: center;
  gap: 12px;
  font-weight: 700;
}

.logo h1 {
  font-size: 18px;
  letter-spacing: 0.5px;
}

.icon-analytics {
  width: 28px;
  height: 28px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='22 12 18 12 15 21 9 3 6 12 2 12'%3E%3C/polyline%3E%3C/svg%3E") center no-repeat;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 16px;
}

.theme-toggle {
  background: rgba(255, 255, 255, 0.15);
  border: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  align-items: center;
  justify-content: center;
}

.theme-toggle:hover {
  background: rgba(255, 255, 255, 0.25);
}

.icon-moon {
  width: 18px;
  height: 18px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z'%3E%3C/path%3E%3C/svg%3E") center no-repeat;
}

.user-profile {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
}

.avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.2);
}

/* 主体内容布局 */
.app-main {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* 左侧侧边栏 */
.sidebar {
  width: 240px;
  background: var(--sidebar-bg);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  transition: var(--transition);
}

.menu {
  padding: 16px 0;
  flex: 1;
  overflow-y: auto;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  color: var(--sidebar-text);
  cursor: pointer;
  transition: var(--transition);
  border-left: 3px solid transparent;
}

.menu-item:hover {
  background: var(--sidebar-item-hover);
  transform: translateX(3px);
}

.menu-item.active {
  background: var(--sidebar-item-active);
  color: var(--sidebar-text-active);
  border-left-color: var(--primary);
  font-weight: 600;
}

.menu-label {
  font-size: 14px;
}

/* 菜单图标样式 */
[class^="icon-"] {
  width: 20px;
  height: 20px;
  opacity: 0.85;
  transition: var(--transition);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  display: inline-block;
}

.menu-item.active [class^="icon-"] {
  opacity: 1;
}

.icon-trend-day {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='22 12 18 12 15 21 9 3 6 12 2 12'%3E%3C/polyline%3E%3C/svg%3E");
}

.icon-trend-hour {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
}

.icon-category {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='8' y1='6' x2='21' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='12' x2='21' y2='12'%3E%3C/line%3E%3Cline x1='8' y1='18' x2='21' y2='18'%3E%3C/line%3E%3Cline x1='3' y1='6' x2='3.01' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='12' x2='3.01' y2='12'%3E%3C/line%3E%3Cline x1='3' y1='18' x2='3.01' y2='18'%3E%3C/line%3E%3C/svg%3E");
}

.icon-goods {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Ccircle cx='8.5' cy='8.5' r='1.5'%3E%3C/circle%3E%3Cpolyline points='21 15 16 10 5 21'%3E%3C/polyline%3E%3C/svg%3E");
}

.icon-funnel {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v20M2 10h20M5 14h14'%3E%3C/path%3E%3C/svg%3E");
}

.icon-rfm {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z'%3E%3C/path%3E%3C/svg%3E");
}

.icon-retention {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E");
}

.icon-error {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f5222d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='15' y1='9' x2='9' y2='15'%3E%3C/line%3E%3Cline x1='9' y1='9' x2='15' y2='15'%3E%3C/line%3E%3C/svg%3E");
  width: 48px;
  height: 48px;
  display: inline-block;
  margin-bottom: 16px;
}

.sidebar-footer {
  padding: 16px;
  border-top: 1px solid var(--border);
}

.copyright {
  color: var(--text-light);
  font-size: 12px;
  text-align: center;
}

.version {
  margin-top: 4px;
  opacity: 0.8;
}

/* 右侧内容区 */
.content-area {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
  background-color: var(--bg-alt);
}

.page-header {
  margin-bottom: 24px;
}

.page-title {
  font-size: 24px;
  font-weight: 600;
  margin-bottom: 8px;
  color: var(--text);
}

.page-desc {
  color: var(--text-light);
  font-size: 14px;
}

.chart-container {
  background-color: var(--card);
  border-radius: 12px;
  box-shadow: var(--card-shadow);
  padding: 24px;
  height: calc(100% - 70px);
  display: flex;
  flex-direction: column;
}

.chart-wrapper {
  flex: 1;
  overflow-y: auto;
  padding-right: 8px;
}

/* 加载状态样式 */
.loading {
  margin: auto;
  text-align: center;
  color: var(--text-light);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.loader {
  width: 48px;
  height: 48px;
  border: 5px solid var(--border);
  border-bottom-color: var(--primary);
  border-radius: 50%;
  animation: rotation 1s linear infinite;
  margin-bottom: 16px;
}

@keyframes rotation {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 错误状态样式 */
.error {
  margin: auto;
  text-align: center;
  color: var(--danger);
  padding: 24px;
}

.btn-retry {
  background-color: var(--primary);
  color: white;
  border: none;
  border-radius: 6px;
  padding: 8px 16px;
  font-size: 14px;
  cursor: pointer;
  transition: var(--transition);
  margin-top: 16px;
}

.btn-retry:hover {
  background-color: var(--primary-dark);
}

/* 响应式设计 */
@media (max-width: 1024px) {
  .sidebar {
    width: 200px;
  }
  
  .content-area {
    padding: 16px;
  }
  
  .chart-container {
    padding: 16px;
  }
}

@media (max-width: 768px) {
  .app-main {
    flex-direction: column;
  }
  
  .sidebar {
    width: 100%;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  
  .menu {
    display: flex;
    flex-wrap: wrap;
    overflow-y: visible;
    padding: 8px 0;
  }
  
  .menu-item {
    flex: 1 1 50%;
    padding: 10px;
    justify-content: center;
  }
  
  .page-title {
    font-size: 20px;
  }
  
  .chart-container {
    height: calc(100% - 50px);
  }
}

@media (max-width: 480px) {
  .app-header {
    padding: 0 12px;
  }
  
  .logo h1 {
    font-size: 16px;
  }
  
  .username {
    display: none;
  }
  
  .menu-item {
    flex: 1 1 100%;
  }
  
  .page-header {
    margin-bottom: 16px;
  }
}
.icon-sun {
  width: 18px;
  height: 18px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='%23ffb300' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3Cpath d='M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42'/%3E%3C/svg%3E") center no-repeat;
}

/* 欢迎页样式 */
.welcome-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
  color: var(--primary-dark);
  background: linear-gradient(135deg, var(--bg-alt) 60%, var(--primary-light) 100%);
  border-radius: 12px;
  box-shadow: var(--card-shadow);
  padding: 48px 16px;
}
.welcome-page h2 {
  font-size: 28px;
  margin-bottom: 16px;
  font-weight: 700;
}
.welcome-time {
  font-size: 20px;
  margin-bottom: 12px;
  color: var(--primary);
  letter-spacing: 1px;
}
.welcome-tip {
  font-size: 16px;
  color: var(--text-light);
}

/* 首页图标 */
.icon-home {
  width: 20px;
  height: 20px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='%23409EFF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='M3 9.5L12 4l9 5.5V20a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9.5z'/%3E%3Cpath d='M9 22V12h6v10'/%3E%3C/svg%3E") center no-repeat;
}
</style>
    